const jwt = require("jsonwebtoken")
const {
  USERNAME_OR_PASSWORD_IS_REQUIRED,
  USERNAME_IS_NOT_EXISTS,
  PASSWORD_IS_INCORRECT,
  NOT_TOKEN,
  UNAUTHORIZATION,
} = require("../config/error-constants")
const { PUBLIC_KEY } = require("../config/screct")
const userService = require("../service/user.service")
const md5password = require("../utils/md5-password")

// 判断用户能否登录
const verifyLogin = async (ctx, next) => {
  const { username, password } = ctx.request.body

  // 1.判断用户名和密码是否为空
  if (!username || !password) {
    return ctx.app.emit("error", USERNAME_OR_PASSWORD_IS_REQUIRED, ctx)
  }
  // 2.查询该用户是否存在数据库中
  const users = await userService.findUserByName(username)
  const user = users[0]
  if (!user) {
    return ctx.app.emit("error", USERNAME_IS_NOT_EXISTS, ctx)
  }
  // 3.查询数据库中密码和用户传递的密码是否一致
  // user.password是数据库里面加密的，password是用户登录的，所以得加密后再判断是否相等
  if (user.password !== md5password(password)) {
    return ctx.app.emit("error", PASSWORD_IS_INCORRECT, ctx)
  }
  // 4.将查询到的用户信息传给下一个中间件,下一个中间件直接通过ctx.user拿到
  ctx.user = user

  // 执行下一个中间件
  await next()
}

// 判断是否已经登录
const verifyAuth = async (ctx, next) => {
  // 1.获取token
  const authrization = ctx.headers.authorization

  // 2.判断token是否存在
  if (!authrization) {
    return ctx.app.emit("error", NOT_TOKEN, ctx)
  }

  // 3.验证token是否有效
  try {
    // 通过公钥去对token解密，解密算法跟加密时的一样("RS256")
    const token = authrization.replace("Bearer ", "")
    const result = jwt.verify(token, PUBLIC_KEY, {
      algorithms: ["RS256"],
    })
    // 将解析后的用户信息保存
    ctx.user = result
    // 执行下一个中间件
    await next()
  } catch (error) {
    // 未授权抛出错误
    ctx.app.emit("error", UNAUTHORIZATION, ctx)
  }
}

module.exports = {
  verifyLogin,
  verifyAuth,
}
